package dsync

import (
	"encoding/json"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

var client = &alidns.Client{}
var domain = "alidns.aliyuncs.com"

func initaliz() {
	log.Println("-------------------DDNS 初始化客户端连接参数--------------------")
	err := client.InitWithAccessKey("cn-beijing", "LTAI4FsFwiVxZgZZjQVYxbeP", "wcnF9Wu5U1EiQsnR7v7nkKcZp2XqMh")
	if err != nil {
		log.Panic("init client err")
	}
}

func Run() {
	initaliz()
	log.Println("DDNS 动态域名解析已启动")
	log.Println("开始运行同步任务, 任务执行间隔时间", Cfg.Sync.Delay, "秒")
	var ch chan int

	ticker := time.NewTicker(time.Second * Cfg.Sync.Delay)
	go func() {
		for range ticker.C {
			handl()
		}
		ch <- 1
	}()
	<-ch
}

func handl() {
	domainName := App.Domain
	rkw := Cfg.Rkws
	currentIP := currentIP()
	if isNil(currentIP) {
		log.Println("同步-获取当前IP失败，下次任务重试..")
		return
	}
	for _, v := range rkw {
		result, err := query(domainName, v.RR, v.Type)
		if err != nil {
			log.Println("同步-查询错误", domainName, v.RR, v.Type, err)
		} else if result != nil {
			records := result.DomainRecords.Record
			if len(records) > 0 {
				record := records[0]
				value := record.Value
				recordId := record.RecordId
				isDNS := currentIP == value
				log.Println("同步-查询", domainName, v.RR, v.Type, records, "有记录", "-当前外网IP", currentIP, "当前解析IP", value, "是否需要重新解析 -", !isDNS)
				if !isDNS {
					update(currentIP, recordId, v.RR, v.Type)
				}
			} else {
				log.Println("同步-查询", domainName, v.RR, v.Type, records, "无记录")
				add(currentIP, domainName, v.RR, v.Type)
			}
		}
	}
}

func query(domainName, rrkeyWord, typ string) (*Result, error) {
	log.Println("查询", domainName, rrkeyWord, typ)
	request := alidns.CreateDescribeDomainRecordsRequest()
	request.SetDomain(domain)
	request.RRKeyWord = rrkeyWord
	request.Type = typ
	request.DomainName = domainName
	response, err := client.DescribeDomainRecords(request)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	if response.GetHttpStatus() == 200 {
		resultBytes := response.GetHttpContentBytes()
		result := Result{}
		err = json.Unmarshal(resultBytes, &result)
		if err != nil {
			log.Println(err)
			return nil, err
		}
		return &result, nil
	}
	log.Println(err)
	return nil, err
}

func update(currentIP, recordId, rr, t string) {
	log.Println("更新解析", currentIP, recordId, rr, t, domain)
	request := alidns.CreateUpdateDomainRecordRequest()
	request.SetDomain(domain)
	request.RR = rr
	request.Type = t
	request.RecordId = recordId
	request.Value = currentIP
	response, err := client.UpdateDomainRecord(request)
	if err != nil {
		log.Println("更新解析-错误", err)
	} else {
		result := response.GetHttpContentString()
		log.Println("更新解析-结果", result)
	}
}

func add(currentIP, domainName, rr, typ string) {
	log.Println("添加解析", currentIP, domainName, rr, typ, domain)
	request := alidns.CreateAddDomainRecordRequest()
	request.SetDomain(domain)
	request.DomainName = domainName
	request.RR = rr
	request.Type = typ
	request.Value = currentIP
	response, err := client.AddDomainRecord(request)
	if err != nil {
		log.Println("添加解析-错误", err)
	} else {
		result := response.GetHttpContentString()
		log.Println("添加解析-结果", result)
	}
}

func currentIP() string {
	resp, err := http.Get("https://jsonip.com")
	if err != nil {
		log.Println("获取当前IP错误", err)
		return ""
	}
	defer resp.Body.Close()
	if resp.StatusCode == 200 {
		body, _ := ioutil.ReadAll(resp.Body)
		result := make(map[string]string)
		_ = json.Unmarshal(body, &result)
		return result["ip"]
	}
	return ""
}
